package com.huohuzhihui.door.service.impl;

import com.huohuzhihui.common.exception.CustomException;
import com.huohuzhihui.door.device.WgUdpCommShort;
import com.huohuzhihui.door.domain.DoorRecord;
import com.huohuzhihui.door.service.IDoorDeviceOperService;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

@Service
public class WgDoorDeviceOperServiceImpl implements IDoorDeviceOperService {
    private String recordDetails[] =
            {
                    //记录原因 (类型中 SwipePass 表示通过; SwipeNOPass表示禁止通过; ValidEvent 有效事件(如按钮 门磁 超级密码开门); Warn 报警事件)
                    //代码  类型   英文描述  中文描述
                    "1", "SwipePass", "Swipe", "刷卡开门",
                    "2", "SwipePass", "Swipe Close", "刷卡关",
                    "3", "SwipePass", "Swipe Open", "刷卡开",
                    "4", "SwipePass", "Swipe Limited Times", "刷卡开门(带限次)",
                    "5", "SwipeNOPass", "Denied Access: PC Control", "刷卡禁止通过: 电脑控制",
                    "6", "SwipeNOPass", "Denied Access: No PRIVILEGE", "刷卡禁止通过: 没有权限",
                    "7", "SwipeNOPass", "Denied Access: Wrong PASSWORD", "刷卡禁止通过: 密码不对",
                    "8", "SwipeNOPass", "Denied Access: AntiBack", "刷卡禁止通过: 反潜回",
                    "9", "SwipeNOPass", "Denied Access: More Cards", "刷卡禁止通过: 多卡",
                    "10", "SwipeNOPass", "Denied Access: First Card Open", "刷卡禁止通过: 首卡",
                    "11", "SwipeNOPass", "Denied Access: Door Set NC", "刷卡禁止通过: 门为常闭",
                    "12", "SwipeNOPass", "Denied Access: InterLock", "刷卡禁止通过: 互锁",
                    "13", "SwipeNOPass", "Denied Access: Limited Times", "刷卡禁止通过: 受刷卡次数限制",
                    "14", "SwipeNOPass", "Denied Access: Limited Person Indoor", "刷卡禁止通过: 门内人数限制",
                    "15", "SwipeNOPass", "Denied Access: Invalid Timezone", "刷卡禁止通过: 卡过期或不在有效时段",
                    "16", "SwipeNOPass", "Denied Access: In Order", "刷卡禁止通过: 按顺序进出限制",
                    "17", "SwipeNOPass", "Denied Access: SWIPE GAP LIMIT", "刷卡禁止通过: 刷卡间隔约束",
                    "18", "SwipeNOPass", "Denied Access", "刷卡禁止通过: 原因不明",
                    "19", "SwipeNOPass", "Denied Access: Limited Times", "刷卡禁止通过: 刷卡次数限制",
                    "20", "ValidEvent", "Push Button", "按钮开门",
                    "21", "ValidEvent", "Push Button Open", "按钮开",
                    "22", "ValidEvent", "Push Button Close", "按钮关",
                    "23", "ValidEvent", "Door Open", "门打开[门磁信号]",
                    "24", "ValidEvent", "Door Closed", "门关闭[门磁信号]",
                    "25", "ValidEvent", "Super Password Open Door", "超级密码开门",
                    "26", "ValidEvent", "Super Password Open", "超级密码开",
                    "27", "ValidEvent", "Super Password Close", "超级密码关",
                    "28", "Warn", "Controller Power On", "控制器上电",
                    "29", "Warn", "Controller Reset", "控制器复位",
                    "30", "Warn", "Push Button Invalid: Disable", "按钮不开门: 按钮禁用",
                    "31", "Warn", "Push Button Invalid: Forced Lock", "按钮不开门: 强制关门",
                    "32", "Warn", "Push Button Invalid: Not On Line", "按钮不开门: 门不在线",
                    "33", "Warn", "Push Button Invalid: InterLock", "按钮不开门: 互锁",
                    "34", "Warn", "Threat", "胁迫报警",
                    "35", "Warn", "Threat Open", "胁迫报警开",
                    "36", "Warn", "Threat Close", "胁迫报警关",
                    "37", "Warn", "Open too long", "门长时间未关报警[合法开门后]",
                    "38", "Warn", "Forced Open", "强行闯入报警",
                    "39", "Warn", "Fire", "火警",
                    "40", "Warn", "Forced Close", "强制关门",
                    "41", "Warn", "Guard Against Theft", "防盗报警",
                    "42", "Warn", "7*24Hour Zone", "烟雾煤气温度报警",
                    "43", "Warn", "Emergency Call", "紧急呼救报警",
                    "44", "RemoteOpen", "Remote Open Door", "操作员远程开门",
                    "45", "RemoteOpen", "Remote Open Door By USB Reader", "发卡器确定发出的远程开门"
            };
    @Override
    public int writeAuth(String sn,String ip,int port,int lockNo,long cardNo,String startTime,String endTime) throws CustomException{
        //连接门禁设备
        WgUdpCommShort pkt = new WgUdpCommShort();
        pkt.iDevSn = Long.parseLong(sn);
        //打开udp连接
        pkt.CommOpen(ip,port);

        pkt.Reset();
        pkt.functionID = (byte) 0x50;
        pkt.iDevSn = Long.parseLong(sn);
        //0D D7 37 00 要添加或修改的权限中的卡号 = 0x0037D70D = 3659533 (十进制)
//        long cardNOOfPrivilege =0x0020726d65;//+ getAccessControlCardNo(bsCardNo);
        long cardNOOfPrivilege = getAccessControlCardNo(cardNo);
        //memcpy(&(pkt.data[0]), &cardNOOfPrivilege, 4);
        System.arraycopy(pkt.longToByte(cardNOOfPrivilege) , 0, pkt.data, 0, 4);
        //20 10 01 01 起始日期:  2010年01月01日   (必须大于2001年)

        pkt.data[4] = (byte)Integer.parseInt(startTime.substring(0,2),16);
        pkt.data[5] = (byte)Integer.parseInt(startTime.substring(2,4),16);
        pkt.data[6] =  (byte)Integer.parseInt(startTime.substring(4,6),16);
        pkt.data[7] = (byte)Integer.parseInt(startTime.substring(6,8),16);
        //20 29 12 31 截止日期:  2029年12月31日
        pkt.data[8] = (byte)Integer.parseInt(endTime.substring(0,2),16);
        pkt.data[9] =(byte)Integer.parseInt(endTime.substring(2,4),16) ;
        pkt.data[10] = (byte)Integer.parseInt(endTime.substring(4,6),16) ;
        pkt.data[11] =(byte)Integer.parseInt(endTime.substring(6,8),16)  ;

        //查询此人此控制器下所有权限，然后形成门字允许禁止的值
        //查询控制器下所有门
        //查询所有授权
        pkt.data[12] = 0x00;
        pkt.data[13] = 0x00;
        pkt.data[14] = 0x00;
        pkt.data[15] = 0x00;
        if (lockNo==1) {
            pkt.data[12] = 0x01;
        }else if(lockNo==2){
            //01 允许通过 二号门 [对双门, 四门控制器有效]
            pkt.data[13] = 0x01;  //如果禁止2号门, 则只要设为 0x00
        }else if(lockNo==3){
            //01 允许通过 三号门 [对四门控制器有效]
            pkt.data[14] = 0x01;
        }else if(lockNo==4){
            //01 允许通过 四号门 [对四门控制器有效]
            pkt.data[15] = 0x01;
        }
        byte[] recvBuff = pkt.run();
        int success =0;
        if (recvBuff != null)
        {
            if (pkt.getIntByByte(recvBuff[8]) == 1)
            {
                //这时 刷卡号为= 0x0037D70D = 3659533 (十进制)的卡, 1号门继电器动作.
                success =1;
                pkt.CommClose();
                return success;
            }
        }else{
            throw new CustomException("设备连接失败");
        }
        pkt.CommClose();

        return success;
    }

    @Override
    public List<DoorRecord> findInoutRecord(String sn,String ip,int port,int lockNo)throws CustomException {
        List<DoorRecord> recordList = new ArrayList<DoorRecord>();

            //连接门禁设备
            WgUdpCommShort pkt = new WgUdpCommShort();
            pkt.iDevSn = Long.parseLong(sn);
            //打开udp连接
            pkt.Type = 0x17;
            pkt.CommOpen(ip,port);

            pkt.Reset();
            pkt.functionID = (byte) 0xB4;
            long recordIndexGot4GetSwipe = 0x0;
            byte[] recvBuff = pkt.run();
            int success = 0;
            if (recvBuff != null) {
                recordIndexGot4GetSwipe = pkt.getLongByByte(recvBuff, 8, 4);
                pkt.Reset();
                pkt.functionID = (byte) 0xB0;
                long recordIndexToGetStart = recordIndexGot4GetSwipe + 1;
                long recordIndexValidGet = recordIndexGot4GetSwipe;
                int cnt = 0;
                do {
                    System.arraycopy(pkt.longToByte(recordIndexToGetStart), 0, pkt.data, 0, 4);
                    recvBuff = pkt.run();
                    success = 0;
                    if (recvBuff != null) {
                        success = 1;

                        //12	记录类型
                        //0=无记录
                        //1=刷卡记录
                        //2=门磁,按钮, 设备启动, 远程开门记录
                        //3=报警记录	1
                        //0xFF=表示指定索引位的记录已被覆盖掉了.  请使用索引0, 取回最早一条记录的索引值
                        int recordType = pkt.getIntByByte(recvBuff[12]);
                        if (recordType == 0) {
                            break; //没有更多记录
                        }

                        if (recordType == 0xff) {
                            success = 0;   //此索引号无效  重新设置索引值
                            //取最早一条记录的索引位
                            int recordIndexToGet = 0;
                            System.arraycopy(pkt.longToByte(recordIndexToGet), 0, pkt.data, 0, 4);

                            recvBuff = pkt.run();
                            success = 0;
                            if (recvBuff != null) {
                                //	  	最早一条记录的信息

                                success = 1;
                                long recordIndex = 0;
                                recordIndex = pkt.getLongByByte(recvBuff, 8, 4);
                                recordIndexToGetStart = recordIndex;
                                continue;
                            }
                            success = 0;
                            break;
                        }
                        recordIndexValidGet = recordIndexToGetStart;
                        //.......对收到的记录作存储处理
                        //去除重复的然后保存
                        DoorRecord doorRecord = displayRecordInformation(recvBuff, lockNo,pkt.iDevSn+"",pkt);

                        recordList.add(doorRecord);
                        //去除重复的然后保存
                    } else {
                        //提取失败

                        break;
                    }
                    recordIndexToGetStart++;
                } while (cnt++ < 200000);
                if (success > 0) {
                    //通过 0xB2指令 设置已读取过的记录索引号  设置的值为最后读取到的刷卡记录索引号
                    pkt.Reset();
                    pkt.functionID = (byte) 0xB2;
                    System.arraycopy(pkt.longToByte(recordIndexValidGet), 0, pkt.data, 0, 4);

                    //12	标识(防止误设置)	1	0x55 [固定]
                    System.arraycopy(pkt.longToByte(pkt.SpecialFlag), 0, pkt.data, 4, 4);

                    recvBuff = pkt.run();
                    success = 0;
                    if (recvBuff != null) {
                        if (pkt.getIntByByte(recvBuff[8]) == 1) {
                            //完全提取成功....
                            success = 1;
                        }
                    }

                }
            }else{
                throw new CustomException("设备连接失败");
            }
            pkt.CommClose();

        return recordList;
    }


    /**
     *
     * @param cardNo 10位一卡通卡号
     * @return 门禁机微耕26 8位卡号
     */
    private static long getAccessControlCardNo(long cardNo){
        long a = cardNo%(256*256) + ((cardNo/(256*256))%256)*100000;
        return a;
    }

    private static void log(String info) //日志信息
    {
        System.out.println(info);
    }

    @Override
    public String getReasonDetailChinese(int Reason) //中文
    {
        if (Reason > 45) {
            return "";
        }
        if (Reason <= 0) {
            return "";
        }
        return recordDetails[(Reason - 1) * 4 + 3]; //中文信息
    }

    private DoorRecord displayRecordInformation(byte[] recvBuff, int lockNo, String sn, WgUdpCommShort pkt) {

        //8-11	最后一条记录的索引号
        //(=0表示没有记录)	4	0x00000000
        long recordIndex = pkt.getLongByByte(recvBuff, 8, 4);

        //12	记录类型
        //0=无记录
        //1=刷卡记录
        //2=门磁,按钮, 设备启动, 远程开门记录
        //3=报警记录	1
        int recordType = pkt.getIntByByte(recvBuff[12]);

        //13	有效性(0 表示不通过, 1表示通过)	1
        int recordValid = pkt.getIntByByte(recvBuff[13]);

        //14	门号(1,2,3,4)	1
        int recordDoorNO = pkt.getIntByByte(recvBuff[14]);
        if(recordDoorNO != lockNo){
            return  null;
        }
        //15	进门/出门(1表示进门, 2表示出门)	1	0x01
        int recordInOrOut = pkt.getIntByByte(recvBuff[15]);

        //16-19	卡号(类型是刷卡记录时)
        //或编号(其他类型记录)	4
        long recordCardNO = pkt.getLongByByte(recvBuff, 16, 4);


        //20-26	刷卡时间:
        //年月日时分秒 (采用BCD码)见设置时间部分的说明
        String recordTime = String.format("%02X%02X-%02X-%02X %02X:%02X:%02X",
                pkt.getIntByByte(recvBuff[20]),
                pkt.getIntByByte(recvBuff[21]),
                pkt.getIntByByte(recvBuff[22]),
                pkt.getIntByByte(recvBuff[23]),
                pkt.getIntByByte(recvBuff[24]),
                pkt.getIntByByte(recvBuff[25]),
                pkt.getIntByByte(recvBuff[26]));

        //2012.12.11 10:49:59	7
        //27	记录原因代码(可以查 "刷卡记录说明.xls"文件的ReasonNO)
        //处理复杂信息才用	1
        int reason = pkt.getIntByByte(recvBuff[27]);
        DoorRecord doorRecord = new DoorRecord();
        doorRecord.setType(recordType);
        //0=无记录
        //1=刷卡记录
        //2=门磁,按钮, 设备启动, 远程开门记录
        //3=报警记录	1
        //0xFF=表示指定索引位的记录已被覆盖掉了.  请使用索引0, 取回最早一条记录的索引值
        if (recordType == 0) {
            log(String.format("索引位=%u  无记录", recordIndex));
        } else if (recordType == 0xff) {
            log(" 指定索引位的记录已被覆盖掉了,请使用索引0, 取回最早一条记录的索引值");
        } else if (recordType == 1) //2015-06-10 08:49:31 显示记录类型为卡号的数据
        {
            doorRecord.setType(1);
            doorRecord.setCardNo(recordCardNO + "");
            doorRecord.setIsIn(recordInOrOut);
            doorRecord.setIsValid(recordValid);
            doorRecord.setLockNo(lockNo+"");
            doorRecord.setSn(sn);

            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                doorRecord.setOpenTime(dateFormat.parse(recordTime));
                doorRecord.setDescription(getReasonDetailChinese(reason));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return  doorRecord;
        } else if (recordType == 2) {

            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            try {
                doorRecord.setType(2);
                doorRecord.setLockNo(lockNo+"");
                doorRecord.setOpenTime(dateFormat.parse(recordTime));
                doorRecord.setDescription(getReasonDetailChinese(reason));
                doorRecord.setSn(sn);

            } catch (ParseException e) {
                e.printStackTrace();
            }
            //其他处理
            //门磁,按钮, 设备启动, 远程开门记录
            return  doorRecord;
        } else if (recordType == 3) {
            doorRecord.setType(3);
            doorRecord.setLockNo(lockNo+"");
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            try {
                doorRecord.setOpenTime(dateFormat.parse(recordTime));
                doorRecord.setDescription(getReasonDetailChinese(reason));
                doorRecord.setSn(sn);
            } catch (ParseException e) {
                e.printStackTrace();
            }

            //其他处理
            //报警记录

            return  doorRecord;
        }
        return  null;
    }
}
